﻿using _80X_CG_Frame.Interfaces;
using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace _80X_CG_Frame.Objects
{
    /// <summary>
    /// 爱普生机器人类
    /// </summary>
    public class 爱普生_Robot : AsyncClient, IRobot
    {
        int maxBufferSize = 1024;
        static int max_fail = 1;//超x次失败重连
        int fail_count;
        //RobotType robot_type;
        string robot_type;


        public 爱普生_Robot()
        {
            fail_count = 0;
            机器人类型 = "爱普生";
        }
        public static Dictionary<string, string> 上料机器手 = new Dictionary<string, string>
        {
            {"第一次拍照触发状态", "11" },
            { "第0次拍照触发状态","10"},
            { "第0次拍照完成","20"},
            { "CG方向","30"},
            { "扫码触发","100"},
            { "扫码完成","200"},
            { "拍照失败抛料","300"},
            { "上料机器人放料完成","400"},
            {"第一次拍照完成", "12" },
            {"机器手旋转偏移角度", "2" },
            {"第二次拍照触发状态", "21" },
            {"第二次拍照完成", "22" },
            {"机器手偏移坐标", "1" },
            {"机器手无偏移坐标", "-1" }
        };
        public static Dictionary<string, string> 下料机器手 = new Dictionary<string, string>
        {
            {"扫码枪触发标志1", "barcode_trigger1" },
            {"扫码枪取结果失败标志1", "barcode_fail1" },
            {"扫码枪取结果完成标志1", "barcode_finish1" },
            {"扫码枪触发标志2", "barcode_trigger2" },
            {"扫码枪取结果失败标志2", "barcode_fail2" },
            {"扫码枪取结果完成标志2", "barcode_finish2" },
            {"下料完成标志", "Place_cg_finish" },
             {"下料完成标志复位", "ResetPlaceCG" },
            {"下料机器手取料失败标志复位", "Reset_cg" },
            {"下料机器手取料失败标志", "get_cg_failed" },
             {"下料扫码失败", "get_code_failed" },
            {"下料扫码成功", "get_code_ok" }
        };

        public string 机器人类型 { get => robot_type; set => robot_type = value; }

        public async Task<bool> RobotConnectAsync(string address, int times = 5)
        {
            bool connected = await ConnectAsync(address, times);
            if (connected)
                ns = client.GetStream();
            return connected;
        }

        /// <summary>
        /// 发送
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        public bool Send(string msg)
        {
            byte[] byteSend = new byte[maxBufferSize];

            lock (client)
            {
                try
                {
                    if (ns != null && IsConnect)
                    {
                        byteSend = Encoding.ASCII.GetBytes(协议格式化(msg));
                        //byteSend = ToByteArray(cmd);
                        //byteSend = Encoding.BigEndianUnicode.GetBytes(cmd);
                        if (ns.CanWrite)
                            ns.Write(byteSend, 0, byteSend.Length);
                        else
                            AutoDisConnect();
                        //ns.Flush();
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                catch (Exception ex)
                {
                    //if (ns != null)
                    //    ns.Close();
                    AutoDisConnect();
                    Console.WriteLine(ex.ToString());
                    return false;
                }

            }

        }

        /// <summary>
        /// 发送带接收
        /// </summary>
        /// <param name="cmd"></param>
        /// <param name="result"></param>
        /// <returns></returns>
        private string Transmit(string msg, ref string result)
        {
            //string msg = "";
            byte[] byteSend = new byte[maxBufferSize];
            byte[] byteReceive = new byte[maxBufferSize];

            lock (client)
            {
                try
                {
                    if (ns != null && IsConnect)
                    {
                        byteSend = Encoding.ASCII.GetBytes(协议格式化(msg));

                        if (ns.CanWrite)
                            ns.Write(byteSend, 0, byteSend.Length);
                        else
                            DisConnect();
                        //ns.Flush();

                        if (ns.CanRead)
                        {
                            do
                            {
                                int len = ns.Read(byteReceive, 0, maxBufferSize);

                                if (len > 0)
                                {
                                    //result = ByteArrayToStr(byteReceive, len);
                                    result = Encoding.ASCII.GetString(byteReceive, 0, len);
                                    //Console.Write("从机器人接收:" + result);
                                }
                                else
                                {
                                    AutoDisConnect();
                                }
                            } while (ns.DataAvailable);
                        }
                        else
                        {
                            DisConnect();
                        }
                    }
                    else
                    {
                        DisConnect();
                    }
                }
                catch (Exception ex)
                {
                    AutoDisConnect();
                    Console.WriteLine(ex.ToString());
                }

            }
            return result;
        }

        public bool 上料机器手第0次拍照触发()
        {
            string result = "";
            Transmit(上料机器手["第0次拍照触发状态"], ref result);
            if (result == " 1\r\n")
                return true;
            return false;

        }
        public bool 上料机器手第0次拍照完成()
        {
            return Send(上料机器手["第0次拍照完成"]);
        }
        public bool 扫码触发()
        {
            string result = "";
            Transmit(上料机器手["扫码触发"], ref result);
            //Console.Write("扫码触发信号:" + result);
            if (result == " 1\r\n")
                return true;
            return false;

        }
        public bool 上料机器人放料完成()
        {
            string result = "";
            Transmit(上料机器手["上料机器人放料完成"], ref result);
            if (result != "")
                return true;
            return false;

        }
        public bool 扫码完成()
        {
            return Send(上料机器手["扫码完成"]);
        }

        public bool 拍照失败抛料()
        {
            return Send(上料机器手["拍照失败抛料"]);
        }
        public bool CG方向(string status)
        {
            string msg = 上料机器手["CG方向"] + ";" + status;//发送角度
            return Send(msg);
        }

        public bool 上料机器手第一次拍照触发()
        {
            string result = "";
            Transmit(上料机器手["第一次拍照触发状态"], ref result);
            if (result == " 1\r\n")
                return true;
            return false;

        }
        public bool 上料机器手第一次拍照偏移(double x, double y, double r)
        {
            string msg = 上料机器手["机器手旋转偏移角度"] + ";" +r;//发送角度
            return Send(msg);
        }
        public bool 上料机器手第一次拍照完成()
        {
            return Send(上料机器手["第一次拍照完成"]);
        }

        public bool 上料机器手第二次拍照触发()
        {

            string result = "";
            Transmit(上料机器手["第二次拍照触发状态"], ref result);
            if (result == " 1\r\n")
                return true;
            return false;
        }
        public bool 上料机器手第二次拍照偏移(double x, double y, double r)
        {
            string msg = 上料机器手["机器手偏移坐标"] + ";" +  x + ";" +  y;//发送x,y偏移
            return Send(msg);
        }
        public bool 上料机器手第二次拍照完成()
        {
            return Send(上料机器手["第二次拍照完成"]);

        }

        public bool 上料机器手无偏移坐标()
        {
            return Send(上料机器手["机器手无偏移坐标"]);

        }


        public bool 下料机器手第一次扫码触发()
        {
            string result = "";
            Transmit(下料机器手["扫码枪触发标志1"], ref result);
            if (result == " 1\r\n")
                return true;
            return false;

        }
        public bool 下料扫码成功()
        {
            return Send(上料机器手["下料扫码成功"]);
        }
        public bool 下料扫码失败()
        {
            return Send(上料机器手["下料扫码失败"]);
        }
        public bool 下料机器手扫码完成()
        {
            return Send(上料机器手["扫码枪取结果完成标志1"]);
        }
        public bool 下料机器手第二次扫码完成()
        {
            return Send(上料机器手["扫码枪取结果完成标志2"]);
        }
        public bool 下料完成()
        {
            string result = "";
            Transmit(下料机器手["下料完成标志"], ref result);
            if (result == " 1\r\n")
                return true;
            return false;

        }
        public bool 下料完成标志复位()
        {
            return Send(下料机器手["下料完成标志复位"]);
        }
        public bool 下料机器手第二次扫码触发()
        {

            string result = "";
            Transmit(下料机器手["扫码枪触发标志2"], ref result);
            if (result == " 1\r\n")
                return true;
            return false;
        }

        public bool 下料机器手取料失败()
        {
            string result = "";
            Transmit(下料机器手["下料机器手取料失败标志"], ref result);
            if (result == " 1\r\n")
                return true;
            return false;
        }

        /// <summary>
        /// 超时自动断连
        /// </summary>
        private void AutoDisConnect()
        {
            fail_count++;
            if(fail_count >= max_fail)
            {
                fail_count = 0;
                DisConnect();
            }
        }

        private string 协议格式化(string msg)
        {
            /*
            if (Robot_type == RobotType.富士康)
                return msg;
            else
            */
            return msg + "\r\n";
        }
    }
    public class 富士康_Robot : AsyncClient, IRobot
    {
        int maxBufferSize = 1024;
        static int max_fail = 500;//超x次失败重连
        int fail_count;
        //RobotType robot_type;
        string robot_type;
        int fail_read_count = 0;
        object tcp_lock = new object();
        string last_read = "0";

        public 富士康_Robot()
        {
            fail_count = 0;
            机器人类型 = "富士康";
        }
        public static Dictionary<string, string> 上料机器手 = new Dictionary<string, string>
        {
            {"上料料盘有", "011" },
            {"第一次拍照完成", "012" },
            {"第二次拍照完成", "013" },
            {"放料", "014" },
            {"cg放反", "020" },
            {"cg未放反", "021" },
            {"cg放反拍照到位", "031" },
            {"第一次拍照到位", "032" },
            {"第二次拍照到位", "033" },
            {"放料完成", "034" }
        };
        public static Dictionary<string, string> 下料机器手 = new Dictionary<string, string>
        {
            {"扫码枪触发标志1", "barcode_trigger1" },
            {"扫码枪取结果失败标志1", "barcode_fail1" },
            {"扫码枪取结果完成标志1", "barcode_finish1" },
            {"扫码枪触发标志2", "barcode_trigger2" },
            {"扫码枪取结果失败标志2", "barcode_fail2" },
            {"扫码枪取结果完成标志2", "barcode_finish2" },
            {"下料扫码失败", "020" },
            {"下料扫码成功", "021" }
        };

        public string 机器人类型 { get => robot_type; set => robot_type = value; }

        public async Task<bool> RobotConnectAsync(string address, int times = 5)
        {
            bool connected = await ConnectAsync(address, times);
            if (connected)
                ns = client.GetStream();
            return connected;
        }

        /// <summary>
        /// 发送
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        public bool Send(string msg)
        {
            byte[] byteSend = new byte[maxBufferSize];

            lock (tcp_lock)
            {
                try
                {
                    if (ns != null && IsConnect)
                    {
                        byteSend = Encoding.ASCII.GetBytes(协议格式化(msg));
                        //byteSend = ToByteArray(cmd);
                        //byteSend = Encoding.BigEndianUnicode.GetBytes(cmd);
                        if (ns.CanWrite)
                            ns.Write(byteSend, 0, byteSend.Length);
                        else
                            DisConnect();
                        //ns.Flush();
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                catch (Exception ex)
                {
                    //if (ns != null)
                    //    ns.Close();
                    DisConnect();
                    Console.WriteLine(ex.ToString());
                    return false;
                }

            }

        }

        /// <summary>
        /// 发送带接收
        /// </summary>
        /// <param name="cmd"></param>
        /// <param name="result"></param>
        /// <returns></returns>
        private string Transmit(string msg, ref string result)
        {
            //string msg = "";
            byte[] byteSend = new byte[maxBufferSize];
            byte[] byteReceive = new byte[maxBufferSize];

            lock (tcp_lock)
            {
                try
                {
                    if (ns != null && IsConnect)
                    {
                        byteSend = Encoding.ASCII.GetBytes(协议格式化(msg));

                        if (ns.CanWrite)
                            ns.Write(byteSend, 0, byteSend.Length);
                        else
                            DisConnect();
                        //ns.Flush();

                        if (ns.CanRead)
                        {
                            do
                            {
                                int len = ns.Read(byteReceive, 0, maxBufferSize);
                                fail_count = 0;
                                if (len > 0)
                                {
                                    //result = ByteArrayToStr(byteReceive, len);
                                    result = Encoding.ASCII.GetString(byteReceive, 0, len);
                                    //Console.WriteLine("robot_receive: " + result);
                                }
                                else
                                {
                                    AutoDisConnect();
                                }
                            } while (ns.DataAvailable);
                        }
                        else
                        {
                            DisConnect();
                        }
                    }
                    else
                    {
                        DisConnect();
                    }
                }
                catch (Exception ex)
                {
                    AutoDisConnect();
                    Console.WriteLine(ex.ToString());
                }

            }
            return result;
        }
        private string Read(ref string result)
        {
            //string msg = "";
            byte[] byteSend = new byte[maxBufferSize];
            byte[] byteReceive = new byte[maxBufferSize];

            lock (tcp_lock)
            {
                try
                {
                    if (ns != null && IsConnect)
                    {

                        if (ns.CanRead)
                        {
                            do
                            {
                                int len = ns.Read(byteReceive, 0, maxBufferSize);
                                fail_count = 0;
                                if (len > 0)
                                {
                                    //result = ByteArrayToStr(byteReceive, len);
                                    result = Encoding.ASCII.GetString(byteReceive, 0, len);
                                    Console.WriteLine(DateTime.Now.ToString("[HH:mm:ss]") + result);
                                }
                                else
                                {
                                    AutoDisConnect();
                                }
                            } while (ns.DataAvailable);
                        }
                        else
                        {
                            DisConnect();
                        }
                    }
                    else
                    {
                        DisConnect();
                    }
                }
                catch (Exception ex)
                {
                    //AutoDisConnect();
                    Console.WriteLine(ex.Message);
                }

            }
            return result;
        }
        public bool 上料机器手第0次拍照触发()
        {
            if (last_read == "0")
                Read(ref last_read);
            if (last_read == "1,")
            {
                last_read = "0";
                return true;
            }

            return false;
        }

        public bool 上料机器手第0次拍照完成()
        {
            return false;
        }

        /// <summary>
        /// 0->OK,1->NG
        /// </summary>
        /// <param name="status"></param>
        /// <returns></returns>
        public bool CG方向(string status)
        {
            string msg;
            if (status == "1")
                msg = 上料机器手["cg放反"];
            else
                msg = 上料机器手["cg未放反"];

            return Send(msg);
        }
        public bool 扫码触发()
        {
            if (last_read == "0")
                Read(ref last_read);
            if (last_read == "1,")
            {
                last_read = "0";
                return true;
            }
            return false;
        }
        public bool 上料机器手第一次拍照触发()
        {
            if (last_read == "0")
                Read(ref last_read);
            if (last_read == "2,")
            {
                last_read = "0";
                return true;
            }
            return false;
        }
        public bool 上料机器手第一次拍照偏移(double x, double y, double r)
        {
            string msg = "00" + "," + x + "," + y + "," + r + "," + "0";//发送角度
            return Send(msg);
        }
        public bool 上料机器手第一次拍照完成()
        {
            return Send(上料机器手["第一次拍照完成"]);
        }

        public bool 上料机器手第二次拍照触发()
        {
            if (last_read == "0")
                Read(ref last_read);
            if (last_read == "3,")
            {
                last_read = "0";
                return true;
            }
            return false;
        }
        public bool 上料机器手第二次拍照偏移(double x, double y, double r)
        {
            string msg = "00" + "," + x + "," + y + "," + r + "," + "0";//发送x,y偏移
            return Send(msg);
        }
        public bool 上料机器手第二次拍照完成()
        {

            return Send(上料机器手["第二次拍照完成"]);

        }
        /*
        public bool 上料料盘有()
        {
            return Send(上料机器手["上料料盘有"]);
        }
        public bool 上料料盘空()
        {
            return Send(上料机器手["上料料盘空"]);
        }
        //public bool 上料盘到位()
        //{
        //    string 上料盘到位 = "";
        //    GLOBAL.plc.ReadMBit(上料机器手["上料盘到位"], ref 上料盘到位);
        //    if (上料盘到位 == "1")
        //        return true;
        //    return false;
        //}
        //public bool 载具到位()
        //{
        //    string 载具到位 = "";
        //    GLOBAL.plc.ReadMBit(上料机器手["上CG治具到位"], ref 载具到位);
        //    if (载具到位 == "0")
        //        return true;
        //    return false;
        //}
        public bool 放料()
        {
            return Send(上料机器手["放料"]);
        }
        public bool 放料完成()
        {
            string result = "0";
            Transmit(上料机器手["放料完成"], ref result);
            if (result == "1,")
                return true;
            return false;
        }
        */
        public bool 下料机器手第一次扫码触发()
        {
            string result = "0";
            //Transmit(上料机器手["第二次拍照到位"], ref result);
            Read(ref result);
            if (result == "1,")
            {
                return true;
            }
            return false;

        }
        public bool 下料机器手第二次扫码触发()
        {

            string result = "0";
            //Transmit(上料机器手["第二次拍照到位"], ref result);
            Read(ref result);
            if (result == "5,")
            {
                return true;
            }
            return false;
        }

        /// <summary>
        /// 超时自动断连
        /// </summary>
        private void AutoDisConnect()
        {
            fail_count++;
            if (fail_count >= max_fail)
            {
                fail_count = 0;
                DisConnect();
            }
        }

        private string 协议格式化(string msg)
        {
            return msg + ";";
        }

        
        public bool 扫码完成()
        {
            throw new NotImplementedException();
        }

        public bool 下料完成()
        {
            throw new NotImplementedException();
        }

        public bool 上料机器人放料完成()
        {
            throw new NotImplementedException();
        }

        public bool 拍照失败抛料()
        {
            throw new NotImplementedException();
        }

        public bool 下料完成标志复位()
        {
            throw new NotImplementedException();
        }

        public bool 上料机器手无偏移坐标()
        {
            throw new NotImplementedException();
        }

        public bool 下料机器手取料失败()
        {
            throw new NotImplementedException();
        }

        public bool 下料扫码成功()
        {
            return Send(下料机器手["下料扫码成功"]);
        }

        public bool 下料扫码失败()
        {
            return Send(下料机器手["下料扫码失败"]);
        }

        public bool 下料机器手扫码完成()
        {
            throw new NotImplementedException();
        }

        public bool 下料机器手第二次扫码完成()
        {
            throw new NotImplementedException();
        }
    }
}
